<?php  if ( ! defined('BASEPATH')) exit('No direct script access allowed');

if ( ! function_exists('is_valid_location_index'))
{
	function is_valid_location_index($var)
	{
		if(is_numeric($var))
		{
			$intkey = intval($var);
			return ($intkey>=1) && ($intkey < 1000000000);
		}
		else
		{
			return false;
		}
	}
}
if ( ! function_exists('is_valid_tag_index'))
{
	function is_valid_tag_index($var)
	{
		if(is_numeric($var))
		{
			$intkey = intval($var);
			return ($intkey>0) && ($intkey < 1000000000);
		}
		else
		{
			return false;
		}
	}
}

if ( ! function_exists('article_distance_from_target'))
{
	function article_distance_from_target($article_candidate, $target_locations_loaded)
	{
        $CI =& get_instance();
        
		if(count($target_locations_loaded) == 0)
		{
			return 0;
		}
	
		$min_distance = 5000;
		//*  Calculate shortest distance between locations in criteria and article
		foreach($CI->articles->load_locations($article_candidate) as $article_location)
		{
			foreach($target_locations_loaded as $target_location)
			{
				$a = location_distance($article_location, $target_location);
				if($min_distance > $a)
				{
					$min_distance = $a;
				}
			}
		}
		return intval($min_distance);
	}
}

if ( ! function_exists('get_parenthood'))
{
	function get_parenthood($maybe_ancestor, $maybe_descendant, $relations)
	{
		// 0 - no relation
		// 1 - same one
		// 2 - direct parent-child
		// 3 - granparent - grandchild
		// etc.
		if($maybe_ancestor == $maybe_descendant)
		{
			//echo '<br/>checking parenthood ' . $maybe_ancestor . ','.$maybe_descendant.'=1';
			return 1;
		}
		
		$shortest_chain = 1000;
		
		for($i=0; $i<count($relations); $i++)
		//foreach($relations as $pair)
		{
			$pair = $relations[$i];
			if($pair->tag_parent == $maybe_ancestor)
			{ 
				$a = get_parenthood($pair->tag_child, $maybe_descendant, $relations);
				//echo '$a='.$a;
				if(($a > 0) && ($a+1 < $shortest_chain))
				{
					$shortest_chain = $a+1;
					//echo '$shortest_chain='.$shortest_chain;
				}
			}
			else if($pair->tag_child == $maybe_descendant)
			{ 
				$a = get_parenthood($maybe_ancestor, $pair->tag_parent, $relations);
				//echo '$a='.$a;				
				if(($a > 0) && ($a+1 < $shortest_chain))
				{
					$shortest_chain = $a+1;
					//echo '$shortest_chain='.$shortest_chain;					
				}
			}
		}
		if($shortest_chain == 1000)
		{
			//echo '<br/>checking parenthood ' . $maybe_ancestor . ','.$maybe_descendant.'=0';
			return 0;
		}
		else
		{
			//echo '<br/>checking parenthood ' . $maybe_ancestor . ','.$maybe_descendant.'=';
			//var_dump($shortest_chain);
		
			return intval($shortest_chain);
		}
	}
}

  
if ( ! function_exists('tag_relevance_to_target'))
{
	function tag_relevance_to_target($article_candidate, $target_tags_loaded)
	{
        $CI =& get_instance();
        
		if(count($target_tags_loaded) == 0)
		{
			return 100;
		}
	
		$max_relevance = 0;
		$tag_relations = $CI->tags->load_relations();
		
		//  Calculate shortest distance between locations in criteria and article
		foreach($CI->articles->load_tags($article_candidate) as $article_tag)
		{
			foreach($target_tags_loaded as $target_tag)
			{
				if($article_tag->idtags == $target_tag)
				{
					return 100;
				}
				$p = get_parenthood($target_tag, $article_tag->idtags, $tag_relations);
				if($p > 0)
				{	
					//to save time, if you have found that target tag is a parent
					//of the article tag, return almost full relevance
					//echo 'relevance='.(100 - $p + 1);
					return 100 - $p + 1;
				}
				
				$p = get_parenthood($article_tag->idtags, $target_tag, $tag_relations);
				if($p > 0)
				{
					if(100 / $p > $max_relevance)
					{
						$max_relevance = 100 / $p;
						//echo 'relevance='.$max_relevance;
					}
					//but do keep checking
				}
				
			}
		}
		//echo 'final relevance='.$max_relevance;
		return $max_relevance;
	}
}

if ( ! function_exists('distance_to_relevance'))
{
	function distance_to_relevance($distance_in_km)
	{
		if($distance_in_km < 20)
		{
			return 100;
		}
		else if($distance_in_km > 4000)
		{
			return 0;
		}
		else
		{
			return intval((398100 - 100*$distance_in_km) / 3980); 
		}
	}
}

if ( ! function_exists('calculate_relevance'))
{
	function calculate_relevance($geodistance, $tag_relevance)
	{
		$geodistance = distance_to_relevance($geodistance);
		
		$result_relevance = ($geodistance + $tag_relevance) / 2;
		if($result_relevance > 80)
		{
			$result_relevance = 100;
		}
		else if($result_relevance < 40)
		{
			$result_relevance = 0;
		}
		return $result_relevance;
	}
}

if ( ! function_exists('search_articles_for_target'))
{
	function search_articles_for_target($locations, $tags, $keywords, $count_limit = 10)
	{
        $CI =& get_instance();
        
		$doecho = false;
	
		if($doecho)
		{
			echo ' locations: '; var_dump($locations);
			echo ' tags: '; var_dump($tags);
			echo ' keywords: '; var_dump($keywords);
			echo '<BR/>';
		}
		//*  $locations, $tags, $keywords can be arrays of location objects, tag objects, strings, or
		//   strings of comma separated keys. Make sure they are arrays of required objects.
		
		//Following is changed
		$locations = $CI->geodata->load_locations($locations); //returns array of full locations
		$tags = $CI->tags->load_tags($tags, false); //false: returns array of ids
        
        if(!$keywords)
        {
            $keywords = array();
        }
        else if(!is_array($keywords))
        {
            $keywords_array = array();
            //this means it is a string, so we will tokenize it
            $tok = strtok($keywords, " \t,.");

            while ($tok !== false) {
                $keywords_array[]=$tok;
                $tok = strtok(" \t,.");
            }
            $keywords = $keywords_array;
        }

		//*  Load all articles 
		$CI->db->from('articles');
        //$CI->db->where('title', 'xxxxxxxxxx');
        
        foreach($keywords as $keyword)
        {
            $CI->db->or_like('title',$keyword);
            $CI->db->or_like('abstract',$keyword);
            $CI->db->or_like('content',$keyword);
        }
        $article_candidate = $CI->db->get()->result();
		
		$targeted_articles = array();

		//For each article 
		foreach($article_candidate as $article_candidate)
		{
			if($doecho) { echo 'article: <b>' . $article_candidate->title . '</b>'; }
			$geodistance = article_distance_from_target($article_candidate, $locations);

			if($doecho) { echo ' geo distance: <b>' . $geodistance . 'km '.distance_to_relevance($geodistance).' points</b>'; }
			
			//   and assign geo relevance
			//	 10km -> 100pts
			//   5000 -> 0 pts
			//   if same country, min 50pts
			//   if neghbouring country, min 30 pts
			
			
			//*  Calculate highest relevance between tags in criteria and article
			$tag_relevance = tag_relevance_to_target($article_candidate, $tags);
			if($doecho) { echo ' tag relevance: <b>' . $tag_relevance . ' points </b>'; }
			//*  Calculate relevance
			$relevance = calculate_relevance($geodistance, $tag_relevance);
			
			//*  Calculate value
			$value = $article_candidate->score;
			if($doecho) { echo ' value: <b>' . $value . ' score points </b>'; }
			
			$current_target_relevance = (50 * $relevance) + $value;
			if($doecho) { echo ' target value: <b>' . $current_target_relevance . ' ts points </b><BR/>'; }

			$article_candidate->value = $value;
			$article_candidate->relevance = $relevance;
			$article_candidate->current_target_relevance = $current_target_relevance;
			$article_candidate->geo_relevance = distance_to_relevance($geodistance);
			$article_candidate->tag_relevance = distance_to_relevance($tag_relevance);
			$article_candidate->target_relevance = distance_to_relevance($relevance);
			
			//*  Add to search results, insert in correct position, and only if among top results
			for($i = 0; $i < count($targeted_articles); $i++)
			{
				if($current_target_relevance > $targeted_articles[$i]->current_target_relevance)
				{	
					$start = array_slice($targeted_articles ,0, $i);
					
					$start[] = $article_candidate;
					if(count($targeted_articles) >= ($count_limit-1))
					{
						$end = array_slice($targeted_articles , $i, ($count_limit - 1) - $i);
					}
					else
					{
						$end = array_slice($targeted_articles , $i);
					}
					$targeted_articles = array_merge($start, $end);
					break;
				}
			}
			if((count($targeted_articles) < $count_limit) && ($i == count($targeted_articles)))
			{
				$targeted_articles[] = $article_candidate;
			}
		}
		//End of loop
		
		if($doecho)
		{
			echo '<BR/><BR/>Selected articlers:<BR/><BR/>';
			//*  Show the array
			foreach($targeted_articles as $targeted_article)
			{
				echo '<b>' . $targeted_article->title . '</b>, target score: <b>' 
						. $targeted_article->current_target_relevance . ' ts points</b><BR/>';
			}
		}	
		//*  Return top results
        return $targeted_articles;
	}
}